﻿<?php
/***
* by ztg
* 配置，要显示什么目录
*/
$config_dir = 'E:/webserver/htdocs';
// $config_dir = '/datas/www/php/test';
// $config_dir = dirname(dirname(dirname(__FILE__)));

date_default_timezone_set('PRC');
error_reporting(E_ALL ^ E_NOTICE);

//处理文件
if (!empty($_GET['do']) && !empty($_GET['path'])) {
    $path = check_file($config_dir, $_GET['path']);

    switch ($_GET['do']) {
        case 'view':
            view($path);
            break;
        case 'down':
            down($path);
            break;
        case 'listen':
            listen($path);
            break;
        case 'dir':
            dir_file_list($config_dir, $_GET['path'] == '/' ? '' : $_GET['path']);
            break;
    }
    exit;
} else {
    $path = check_dir($config_dir, $_GET['dir'] ?: '/', false);
}

////////////////////////////////////////////////////////

/***
* 监听文件内容变化
*/
function listen($path) {
    $file_size = $_GET['file_size'];
    $file_content = '';

    for ($i = 0; $i < 20; $i ++) {
        clearstatcache();
        $file_size_new = filesize($path);
        if ($file_size_new > $file_size) {
            $file_content = substr(file_get_contents($path), $file_size);
            break;
        }
        sleep(1);
    }
    ajax($file_content, $file_size_new, 0);
}

/***
* 下载文件
*/
function down($path) {
    // 输入文件标签
    header("Content-type: application/octet-stream; charset=gbk");
    header("Accept-Ranges: bytes");
    header("Accept-Length: " . filesize($path));
    header("Content-Disposition: attachment; filename=" . basename($path));

    ob_clean();
    flush();
    $file = fopen($path, "r"); // 打开文件
    echo fread($file, filesize($path)); // 输出文件内容
    fclose($file);
}

/***
* 预览文件
*/
function view($path) {
    if (filesize($path) > 1024 * 1024 *  10) {
        echo '文件超过10M';exit;
    }
    $exts = explode('.', $_GET['path']);
    if (in_array(strtolower(end($exts)), ['jpg', 'jpeg', 'png', 'gif', 'bmp'])) {
        echo '<img src="data:image/jpeg;base64,'. base64_encode(file_get_contents($path)) .'" style="max-width:100%;" />';
    } else {
        echo file_get_contents($path);
    }
}

/***
* ajax返回内容
*/
function ajax($data, $info, $code = 0) {
    header('Content-Type: application/json; charset=utf-8');
    echo json_encode(['data' => $data, 'info' => $info, 'code' => $code], 320);
    exit;
}

/***
* 检查目录是否合法
*/
function check_dir($config_dir, $path, $real = true) {
    $path = preg_replace('/[\/]+/', '/', str_replace('..', '', $path));
    if (substr($config_dir . $path, 0, strlen($config_dir)) != $config_dir) {
        ajax('', 'path error.', -1);
    }
    return $real ? $config_dir . $path : $path;
}

/***
* 检查文件是否合法
*/
function check_file($config_dir, $path) {
    $path = check_dir($config_dir, $path, false);
    $path = $config_dir . $path;
    if (file_exists($path) || is_dir($path)) {
        return $path;
    } else {
        ajax($path, 'path error.', -2);
    }
}

/***
* 目录和文件列表
*/
function dir_file_list($config_dir, $view_dir) {
    $self_name = basename( __FILE__ );
    $script_file_path = str_replace('\\', '/', $_SERVER['SCRIPT_FILENAME']);

    $dir = isset($view_dir) ? $view_dir :  '';
    $dir = $config_dir . $dir;
    // echo $dir;exit;
    $dir = preg_replace('/[\/]+/', '/', str_replace('..', '', $dir));
    if (substr($dir, 0, strlen($config_dir)) != $config_dir) {
        $dir = '';
    }

    $html_head = '当前路径： <a href="'. $self_name .'">.</a>';

    $dir_list = explode('/', substr($dir, strlen($config_dir)));
    $dir_temp = '';
    foreach ($dir_list as $dir_value) {
        $dir_temp .= $dir_value . '/';
        $html_head .= '<a href="' . $self_name .'?dir='. substr($dir_temp, 0, -1) .'" title="'. $dir_temp .'">'. $dir_value .'</a> / ';
    }
    $html_head = substr(trim($html_head), 0, -1);
    $html_head .= '<br /><br /><hr size="1" /><br />';

    for ($i = 0; $i < 20; $i ++) {
        $html_file = '';
        $html_dir = '';
        if((@$dh = opendir($dir)) != false){
             while(($file_name = readdir($dh)) != false){
                @$file_name = iconv("gb2312","UTF-8", $file_name);
                $file_path  = $dir. '/'. $file_name;
                $file_path_show = substr($file_path, 0);
                if( str_replace('\\', '/', $file_path) != $script_file_path){

                    $href_dir = $self_name.'?dir='.$file_path;
                    if( substr($file_path, -1) == '.' && substr($file_path, -2) != '..' && !isset($view_dir) ){
                        $href_dir = $self_name;
                    }
                    elseif( substr($file_path, -1) == '.' && substr($file_path, -2) != '..' && isset($view_dir) ){
                        $href_dir = $self_name.'?dir='.$view_dir;
                    }
                    elseif( substr($file_path, -2) == '..' && isset($view_dir) && strlen($file_path) > 5 && substr($file_path, -5, -3) != '..'){
                        $href_dir = $self_name.'?dir='.substr($view_dir, 0, strrpos($view_dir, '/'));
                    }

                    if( is_dir($file_path) ) {
                        $html_dir .= '<tr onmouseover="this.style.background=\'#eee\';" onmouseout="this.style.background=\'#fff\';">
                            <td><a href="'.$href_dir.'">'.$file_path_show.'</a></td>
                            <td></td>
                            <td class="time">'. date('Y-m-d H:i:s', filemtime($file_path)) .'</td>
                            <td></td>
                            </tr>';
                    }
                    else {
                        $view_url = $self_name . '?do=view&path=' . $file_path;
                        $down_url = $self_name . '?do=down&path=' . $file_path;
                        @$file_size = convert(filesize($file_path));
                        $listen_url = '';
                        if (@in_array(strtolower(end(explode('.', $file_path))), ['log', 'txt', 'out'])) {
                            $listen_url = $self_name . '?do=listen&path=' . $file_path;
                            $listen_url = '<a href="javascript:;" class="listen-file" data-href="'. $listen_url .'" title="下载">监听</a>';
                        }

                        $html_file .=  '
                            <tr onmouseover="this.style.background=\'#eee\';" onmouseout="this.style.background=\'#fff\';">
                                <td><a href="'. $view_url .'" class="preview" target="_blank" title="预览">'.$file_path_show.'</a></td>
                                <td>'. $file_size .'</td>
                                <td class="time">'. date('Y-m-d H:i:s', @filemtime($file_path)) .'</td>
                                <td><a href="'. $view_url .'" class="preview" target="_blank" title="预览">预览</a></td>
                                <td><a href="'. $down_url .'" title="下载">下载</a></td>
                                <td>'. $listen_url .'</td>
                            </tr>';

                    }
                }
            }

        }
        @closedir($dh);
        $html_dir = str_replace($config_dir, '', $html_dir);
        $html_file = str_replace($config_dir, '', $html_file);

        $html = $html_head . '<table>' . $html_dir . $html_file .'</table>';
        $md5 = md5($html);
        $new = $md5 != $_GET['md5'];
        if ($new) {
            break;
        } else {
            sleep(1);
        }
    }

    ajax($new ? $html : '', $md5, $new ? 0 : 1);
}

/***
*转换占用空间的值
*/
function convert($size) {
    $unit = array('b','Kb','Mb','Gb','Tb','Pb');
    return @round($size/pow(1024,($i=floor(log($size,1024)))),2) . '' . $unit[$i];
}
?>
<!DOCTYPE>
<html>
<head>
<meta charset="utf-8" />
<script src="https://apps.bdimg.com/libs/jquery/1.8.2/jquery.min.js" type="text/javascript" charset="utf-8"></script>
<title><?php echo $path;?> - 目录列表</title>
<style>
* {
	font-size:14px;
	margin:0;
	padding:0;
}
body {
	padding:6px;
	font-family:"宋体"
}
a {
	text-decoration:none
}
table {
	border-collapse:collapse;
	border-spacing:0;
}
td {
	padding:1px 10px;
}
a {
	color:green;
}
label {
    cursor:pointer;
}
.main {
    padding-bottom:50px;
}
.time {
	color:#4b4b4b;
}

</style>
</head>
<body>
<div id="main" class="main">
    <table>
        <tr>
            <td id="dir-file-list" data-path="<?php echo $path;?>" data-md5="">
            </td>
            <td valign="top">
                <label title="勾选后鼠标移到 [ 预览 ] 按钮上可快捷预览文件内容">
                    快速预览
                    <input type="checkbox" id="preview-status" >
                </label>
                <div style="display:none; position: fixed;right: 0;">
                    <textarea style="width:800px;height:400px;padding:4px;"></textarea>
                    <div>
                        <a href="javascript:;" id="listen-close">关闭</a>
                    </div>
                </div>
            </td>
        </tr>
    </table>
    <div id="preview-box" style="position:fixed;background:#fff;display:none;width:500px;border:1px solid #ccc">
        <h3 style="padding:0 10px 10px 10px;margin:10px 0;border-bottom:1px solid #eee;">预览内容</h3>
        <iframe width="100%" height="100%" border="0" style="border:0;height:200px;"></iframe>
    </div>
</div>
</body>
</html>
<script>
$(document).ready(function () {
    //监听目录内容
    ;(function () {
        var contentBoxObj = $('#dir-file-list');
        function get_dir_file_list () {
            var path = contentBoxObj.attr('data-path');
            var md5 = contentBoxObj.attr('data-md5');

            $.ajax({
                url: '?do=dir&path=' + path + '&md5=' + md5,
                success: function (res) {
                    if (res.code === 0) {
                        contentBoxObj.html(res.data).attr('data-md5', res.info)
                    } else {

                    }
                    setTimeout(function () {
                        get_dir_file_list();
                    }, 200);
                },
                error: function (res) {
                    setTimeout(function () {
                        get_dir_file_list();
                    }, 200);
                },
            })
        }

        get_dir_file_list();

    })();

    //监听文件内容变化
    ;(function () {
        var file_size, url, timers = [], contentObj = $('textarea');;
        window.ajaxObjs = {};

        function listen ($this) {
            file_size = $this.attr('data-file-size') || 0;
            url = $this.attr('data-href') + '&file_size=' + file_size;

            var ajaxObjKey = ('' + Math.random()).substr(2);
            var ajaxObj = $.ajax({
                url: url,
                success: function (res) {
                    if (res.code === 0) {
                        contentObj.val(contentObj.val() + res.data).scrollTop(999999);
                        $this.attr('data-file-size', res.info)
                    } else {
                        if (!confirm(res.info)) {
                            return;
                        }
                    }
                    var timer = setTimeout(function () {
                        listen ($this);
                    }, 200);
                    timers.push(timer);
                    delete ajaxObjs[ajaxObjKey];
                },
                error: function (res) {
                    if (res.statusText != 'abort') {
                        var timer = setTimeout(function () {
                            listen ($this);
                        }, 200);
                        timers.push(timer);
                    }
                },
            })
            ajaxObjs[ajaxObjKey] = ajaxObj;
        }

        function ajax_abort () {
            for (var i in timers) {
                var timer = timers[i];
                timer && clearTimeout(timer);
            }

            console.log(ajaxObjs)
            for (var i in ajaxObjs) {
                var ajaxObj = ajaxObjs[i];
                // console.log(i, ajaxObj)
                ajaxObj.abort();
                delete ajaxObjs[i];
            }

        }

        $('.listen-file').live('click', function () {
            contentObj.val('').parent().show();

            ajax_abort();

            var $this = $(this);
            setTimeout(function () {
                listen ($this);
            }, 200);
        })

        $('#listen-close').click(function () {
            contentObj.val('').parent().hide();

            ajax_abort();
        })

    })();

    // 快捷预览文件
    ;(function () {
        var previewBoxObj = $('#preview-box');
        var previewIframeObj = previewBoxObj.find('iframe');

        var previewBoxWidth = previewBoxObj.width(), previewBoxHeight = previewBoxObj.height(),
            windowWidthHalf = $(window).width() / 2, windowHeightHalf = $(window).height() / 2,
            t, l, r, b;

        $('.preview').live('mouseenter', function (e) {
            if (!$('#preview-status').attr('checked')) {
                return;
            }
            previewIframeObj.attr('src', '').attr('src', $(this).attr('href'));

            if (e.clientX < windowWidthHalf) {
                l = e.clientX + 10;;
                r = 'auto';
            } else {
                l = 'auto';
                r = windowWidthHalf * 2 - e.clientX + 20;
            }
            if (e.clientY < windowHeightHalf) {
                t = e.clientY - 10;
                b = 'auto';
            } else {
                t = 'auto';
                b = windowHeightHalf * 2 - e.clientY - 20;
            }
            previewBoxObj.show().css({top: t, left:l, right:r, bottom:b})
        });

        previewBoxObj.mouseleave(function () {
            $(this).hide();
        })
        $('#main').mouseleave(function () {
            previewBoxObj.hide();
        })
    })();
})
</script>